﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BuildOptimizer
{
    class BoDecisionNode
    {
        private BoGameState _gameState = new BoGameState();
        private bool[] _isCommandRequired = new bool[Enum.GetNames(typeof(commandID)).Length];
        private bool[] _isCommandUnlocked = new bool[Enum.GetNames(typeof(commandID)).Length];

        private BoCommand _command = null;
        private BoDecisionNode _parent = null;
        private List<BoDecisionNode> _children = new List<BoDecisionNode>();
        private List<int> _childrenCommandCodeLog = new List<int>();

        public BoDecisionNode(BoDecisionNode parent, BoCommand command)
        {
            _parent = parent;
            _command = command;
        }
        public BoDecisionNode(BoDecisionNode parent, BoCommand command, BoDecisionNode node)
        {
            _parent = parent;
            _command = command;

            _gameState = node.gameState.clone();
            for (int i = 0; i < Enum.GetNames(typeof(commandID)).Length; i++)
            {
                _isCommandRequired[i] = node.isCommandRequired[i];
                _isCommandUnlocked[i] = node.isCommandUnlocked[i];
            }
        }
        private BoDecisionNode(BoDecisionNode n)
        {
            _parent = n.parent;
            _command = n.command;

            _gameState = n.gameState.clone();
            for (int i = 0; i < Enum.GetNames(typeof(commandID)).Length; i++)
            {
                _isCommandRequired[i] = n.isCommandRequired[i];
                _isCommandUnlocked[i] = n.isCommandUnlocked[i];
            }
            for (int i = 0; i < n.childrenCommandCodeLog.Count; i++)
            {
                _childrenCommandCodeLog.Add(n.childrenCommandCodeLog[i]);
            }
        }
        public BoDecisionNode cloneWithoutChildren()
        {
            return new BoDecisionNode(this);
        }

        public void executeCommand(BoGoal goal)
        {
            _command.execute(goal, this);
        }

        public bool hasChildren()
        {
            return (_children.Count > 0);
        }
        public bool hasNoChildren()
        {
            return (_children.Count == 0);
        }

        public BoCommand command
        {
            get
            {
                return _command;
            }
        }
        public BoDecisionNode parent
        {
            get
            {
                return _parent;
            }
        }
        public BoDecisionNode leftChild
        {
            get
            {
                return _children[0];
            }
        }
        public List<BoDecisionNode> children
        {
            get
            {
                return _children;
            }
        }
        public void addChild(BoDecisionNode node)
        {
            _children.Add(node);
            _childrenCommandCodeLog.Add(node._command.getCommandCode());
        }
        public void removeChild(BoDecisionNode node)
        {
            int i = 0;
            while (_children[i] != node)
            {
                i++;
            }
            _children.RemoveAt(i);
        }
        public List<int> childrenCommandCodeLog
        {
            get
            {
                return _childrenCommandCodeLog;
            }
        }

        public BoGameState gameState
        {
            get
            {
                return _gameState;
            }
        }
        public bool[] isCommandRequired
        {
            get
            {
                return _isCommandRequired;
            }
        }
        public bool[] isCommandUnlocked
        {
            get
            {
                return _isCommandUnlocked;
            }
        }
        public void unlockCommand(int commandID)
        {
            _isCommandUnlocked[commandID] = true;
        }
        public void dismissCommand(int commandID)
        {
            _isCommandRequired[commandID] = false;
        }
    }
}
